package cn.wenhe9.novel.service.impl;

import cn.wenhe9.novel.constant.DatabaseConsts;
import cn.wenhe9.novel.constant.ResultCodeEnum;
import cn.wenhe9.novel.domain.dto.*;
import cn.wenhe9.novel.domain.entity.book.BookChapter;
import cn.wenhe9.novel.domain.entity.book.BookComment;
import cn.wenhe9.novel.domain.entity.book.BookContent;
import cn.wenhe9.novel.domain.entity.book.BookInfo;
import cn.wenhe9.novel.domain.entity.user.UserInfo;
import cn.wenhe9.novel.domain.vo.*;
import cn.wenhe9.novel.exception.NovelException;
import cn.wenhe9.novel.manager.*;
import cn.wenhe9.novel.mapper.BookChapterMapper;
import cn.wenhe9.novel.mapper.BookCommentMapper;
import cn.wenhe9.novel.mapper.BookContentMapper;
import cn.wenhe9.novel.mapper.BookInfoMapper;
import cn.wenhe9.novel.result.PageResultDto;
import cn.wenhe9.novel.result.ResultResponse;
import cn.wenhe9.novel.service.BookService;
import cn.wenhe9.novel.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 小说模块 服务实现类
 *
 * @author DuJinliang
 * 2022/5/18
 */
@Service
@Slf4j
public class BookServiceImpl implements BookService {

    @Resource
    private BookCategoryCacheManager bookCategoryCacheManager;

    @Resource
    private BookRankCacheManager bookRankCacheManager;

    @Resource
    private BookInfoCacheManager bookInfoCacheManager;

    @Resource
    private BookChapterCacheManager bookChapterCacheManager;

    @Resource
    private BookContentCacheManager bookContentCacheManager;

    @Resource
    private UserDaoManager userDaoManager;

    @Resource
    private BookInfoMapper bookInfoMapper;

    @Resource
    private BookChapterMapper bookChapterMapper;

    @Resource
    private BookCommentMapper bookCommentMapper;

    @Resource
    private BookContentMapper bookContentMapper;

    private static final Integer REC_BOOK_COUNT = 4;

    @Override
    public ResultResponse<PageResultDto<BookInfoDto>> searchBooks(BookQueryVo condition) {
        Page<BookInfoDto> page = new Page<>();
        page.setCurrent(condition.getPageNum());
        page.setSize(condition.getPageSize());
        List<BookInfo> bookInfos = bookInfoMapper.searchBooks(page, condition);
        return ResultResponse.ok(
                PageResultDto.of(
                        condition.getPageNum(),
                        condition.getPageSize(),
                        page.getTotal(),
                        bookInfos.stream().map(item -> BookInfoDto.builder()
                            .id(item.getId())
                            .bookName(item.getBookName())
                            .categoryId(item.getCategoryId())
                            .categoryName(item.getCategoryName())
                            .authorId(item.getAuthorId())
                            .authorName(item.getAuthorName())
                            .wordCount(item.getWordCount())
                            .lastChapterName(item.getLastChapterName())
                            .build()).collect(Collectors.toList())));
    }

    @Override
    public ResultResponse<List<BookRankDto>> listVisitRankBooks() {
        return ResultResponse.ok(bookRankCacheManager.listVisitRankBooks());
    }

    @Override
    public ResultResponse<List<BookRankDto>> listNewestRankBooks() {
        return ResultResponse.ok(bookRankCacheManager.listNewestRankBooks());
    }

    @Override
    public ResultResponse<List<BookRankDto>> listUpdateRankBooks() {
        return ResultResponse.ok(bookRankCacheManager.listUpdateRankBooks());
    }

    @Override
    public ResultResponse<BookInfoDto> getBookById(Long bookId) {
        return ResultResponse.ok(bookInfoCacheManager.getBookInfo(bookId));
    }

    @Override
    public BookChapterAboutDto getLastChapterAbout(Long bookId) {
        //TODO 可以使用线程池优化

        // 查询小说信息
        BookInfoDto bookInfo = bookInfoCacheManager.getBookInfo(bookId);

        // 查询最新章节信息
        BookChapterDto bookChapter = bookChapterCacheManager.getChapter(bookInfo.getLastChapterId());

        // 查询章节内容
        String content = bookContentCacheManager.getBookContent(bookInfo.getLastChapterId());

        // 查询章节总数
        QueryWrapper<BookChapter> chapterQueryWrapper = new QueryWrapper<>();
        chapterQueryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId);
        Long chapterTotal = Long.valueOf(bookChapterMapper.selectCount(chapterQueryWrapper));

        // 组装数据并返回
        return BookChapterAboutDto.builder()
                .chapterInfo(bookChapter)
                .chapterTotal(chapterTotal)
                .contentSummary(content.length() > 30 ? content.substring(0, 30) : content)
                .build();
    }

    @Override
    public ResultResponse<List<BookInfoDto>> listRecBooks(Long bookId) throws NoSuchAlgorithmException {
        Long categoryId = bookInfoCacheManager.getBookInfo(bookId).getCategoryId();
        List<Long> lastUpdateIdList = bookInfoCacheManager.getLastUpdateIdList(categoryId);
        List<BookInfoDto> respDtoList = new ArrayList<>();
        List<Integer> recIdIndexList = new ArrayList<>();
        int count = 0;
        Random rand = SecureRandom.getInstanceStrong();
        while (count < REC_BOOK_COUNT) {
            int recIdIndex = rand.nextInt(lastUpdateIdList.size());
            if (!recIdIndexList.contains(recIdIndex)) {
                recIdIndexList.add(recIdIndex);
                bookId = lastUpdateIdList.get(recIdIndex);
                BookInfoDto bookInfo = bookInfoCacheManager.getBookInfo(bookId);
                respDtoList.add(bookInfo);
                count++;
            }
        }
        return ResultResponse.ok(respDtoList);
    }

    @Override
    public ResultResponse<Void> addVisitCount(Long bookId) {
        bookInfoMapper.addVisitCount(bookId);
        return ResultResponse.ok();
    }

    @Override
    public ResultResponse<Long> getPreChapterId(Long chapterId) {
        // 查询小说ID 和 章节号
        BookChapterDto chapter = bookChapterCacheManager.getChapter(chapterId);
        Long bookId = chapter.getBookId();
        Integer chapterNum = chapter.getChapterNum();

        // 查询上一章信息并返回章节ID
        QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId)
                .lt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum)
                .orderByDesc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM)
                .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql());
        return ResultResponse.ok(
                Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper))
                        .map(BookChapter::getId)
                        .orElse(null)
        );
    }

    @Override
    public ResultResponse<Long> getNextChapterId(Long chapterId) {
        // 查询小说ID 和 章节号
        BookChapterDto chapter = bookChapterCacheManager.getChapter(chapterId);
        Long bookId = chapter.getBookId();
        Integer chapterNum = chapter.getChapterNum();

        // 查询下一章信息并返回章节ID
        QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId)
                .gt(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM, chapterNum)
                .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM)
                .last(DatabaseConsts.SqlEnum.LIMIT_1.getSql());
        return ResultResponse.ok(
                Optional.ofNullable(bookChapterMapper.selectOne(queryWrapper))
                        .map(BookChapter::getId)
                        .orElse(null)
        );
    }

    @Override
    public ResultResponse<List<BookChapterDto>> listChapters(Long bookId) {
        QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId)
                .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM);
        return ResultResponse.ok(bookChapterMapper.selectList(queryWrapper).stream().map(v -> BookChapterDto.builder()
                .id(v.getId())
                .chapterName(v.getChapterName())
                .build()).collect(Collectors.toList()));
    }

    @Override
    public ResultResponse<List<BookCategoryDto>> listCategory(Integer workDirection) {
        return ResultResponse.ok(bookCategoryCacheManager.listCategory(workDirection));
    }

    @Override
    public ResultResponse<Void> saveComment(UserCommentVo dto) {
        BookComment bookComment = new BookComment();
        bookComment.setBookId(dto.getBookId());
        bookComment.setUserId(dto.getUserId());
        bookComment.setCommentContent(dto.getCommentContent());
        bookComment.setCreateTime(LocalDateTime.now());
        bookComment.setUpdateTime(LocalDateTime.now());
        bookCommentMapper.insert(bookComment);
        return ResultResponse.ok();
    }

    @Override
    public BookContentAboutDto getBookContentAbout(Long chapterId) {
        // 查询章节信息
        BookChapterDto bookChapter = bookChapterCacheManager.getChapter(chapterId);

        // 查询章节内容
        String content = bookContentCacheManager.getBookContent(chapterId);

        // 查询小说信息
        BookInfoDto bookInfo = bookInfoCacheManager.getBookInfo(bookChapter.getBookId());

        // 组装数据并返回
        return BookContentAboutDto.builder()
                .bookInfo(bookInfo)
                .chapterInfo(bookChapter)
                .bookContent(content)
                .build();
    }

    @Override
    public ResultResponse<BookCommentDto> listNewestComments(Long bookId) {
        // 查询评论总数
        QueryWrapper<BookComment> commentCountQueryWrapper = new QueryWrapper<>();
        commentCountQueryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, bookId);
        Long commentTotal = Long.valueOf(bookCommentMapper.selectCount(commentCountQueryWrapper));
        BookCommentDto bookCommentRespDto = BookCommentDto.builder().commentTotal(commentTotal).build();
        if (commentTotal > 0) {

            // 查询最新的评论列表
            QueryWrapper<BookComment> commentQueryWrapper = new QueryWrapper<>();
            commentQueryWrapper.eq(DatabaseConsts.BookCommentTable.COLUMN_BOOK_ID, bookId)
                    .orderByDesc(DatabaseConsts.CommonColumnEnum.CREATE_TIME.getName())
                    .last(DatabaseConsts.SqlEnum.LIMIT_5.getSql());
            List<BookComment> bookComments = bookCommentMapper.selectList(commentQueryWrapper);

            // 查询评论用户信息，并设置需要返回的评论用户名
            List<Long> userIds = bookComments.stream().map(BookComment::getUserId).collect(Collectors.toList());
            List<UserInfo> userInfos = userDaoManager.listUsers(userIds);
            Map<Long, String> userInfoMap = userInfos.stream().collect(Collectors.toMap(UserInfo::getId, UserInfo::getUsername));
            List<BookCommentDto.CommentInfo> commentInfos = bookComments.stream()
                    .map(v -> BookCommentDto.CommentInfo.builder()
                            .id(v.getId())
                            .commentUserId(v.getUserId())
                            .commentUser(userInfoMap.get(v.getUserId()))
                            .commentContent(v.getCommentContent())
                            .commentTime(v.getCreateTime()).build()).collect(Collectors.toList());
            bookCommentRespDto.setComments(commentInfos);
        } else {
            bookCommentRespDto.setComments(Collections.emptyList());
        }
        return ResultResponse.ok(bookCommentRespDto);
    }

    @Override
    public ResultResponse<Void> deleteComment(Long userId, Long commentId) {
        QueryWrapper<BookComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), commentId)
                .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId);
        bookCommentMapper.delete(queryWrapper);
        return ResultResponse.ok();
    }

    @Override
    public ResultResponse<Void> updateComment(Long userId, Long id, String content) {
        QueryWrapper<BookComment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.CommonColumnEnum.ID.getName(), id)
                .eq(DatabaseConsts.BookCommentTable.COLUMN_USER_ID, userId);
        BookComment bookComment = new BookComment();
        bookComment.setCommentContent(content);
        bookCommentMapper.update(bookComment, queryWrapper);
        return ResultResponse.ok();
    }

    @Override
    public PageResultDto<BookInfoDto> listBookPageByAuthorId(Long authorId, Long page, Long limit) {
        LambdaQueryWrapper<BookInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BookInfo::getAuthorId, authorId);
        Page<BookInfo> bookInfoPage = bookInfoMapper.selectPage(new Page<>(page, limit), queryWrapper);
        return PageResultDto.of(
                page,
                limit,
                bookInfoPage.getTotal(),
                bookInfoPage.getRecords().stream()
                        .map(bookInfo -> BookInfoDto.builder()
                                .id(bookInfo.getId())
                                .bookName(bookInfo.getBookName())
                                .bookDesc(bookInfo.getBookDesc())
                                .bookStatus(bookInfo.getBookStatus())
                                .authorId(bookInfo.getAuthorId())
                                .authorName(bookInfo.getAuthorName())
                                .categoryId(bookInfo.getCategoryId())
                                .categoryName(bookInfo.getCategoryName())
                                .commentCount(bookInfo.getCommentCount())
                                .lastChapterId(bookInfo.getLastChapterId())
                                .picUrl(bookInfo.getPicUrl())
                                .visitCount(bookInfo.getVisitCount())
                                .wordCount(bookInfo.getWordCount())
                                .updateTime(bookInfo.getUpdateTime())
                                .build()).collect(Collectors.toList()));
    }

    @Override
    public void publishBook(BookPublishVo vo, Long authorId, String penName) {
        if (this.queryByBookNameAndPenName(vo.getBookName(), penName) != null){
            throw new NovelException(ResultCodeEnum.BOOK_NAME_EXISTS);
        }

        BookInfo bookInfo = new BookInfo();
        bookInfo.setWorkDirection(vo.getWorkDirection());
        bookInfo.setCategoryId(vo.getCategoryId());
        bookInfo.setCategoryName(vo.getCategoryName());
        bookInfo.setPicUrl(vo.getPicUrl());
        bookInfo.setBookName(vo.getBookName());
        bookInfo.setAuthorId(authorId);
        bookInfo.setAuthorName(penName);
        bookInfo.setBookDesc(vo.getBookDesc());
        bookInfo.setScore(6);
        bookInfo.setBookStatus(0);
        bookInfo.setVisitCount(0L);
        bookInfo.setWordCount(0);
        bookInfo.setCommentCount(0);
        bookInfo.setIsVip(vo.getIsVip());
        bookInfo.setCreateTime(LocalDateTime.now());
        bookInfo.setUpdateTime(LocalDateTime.now());

        bookInfoMapper.insert(bookInfo);
    }

    @Override
    public Long queryByBookNameAndPenName(String bookName, String penName) {
        LambdaQueryWrapper<BookInfo> queryWrapper = new LambdaQueryWrapper<BookInfo>();
        queryWrapper.eq(BookInfo::getBookName, bookName);
        queryWrapper.eq(BookInfo::getAuthorName, penName);

        BookInfo bookInfo = bookInfoMapper.selectOne(queryWrapper);
        if (bookInfo != null){
            return bookInfo.getId();
        }
        return null;
    }

    @Override
    public PageResultDto<BookChapterDto> listChaptersByPage(Long page, Long limit, Long bookId) {
        QueryWrapper<BookChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(DatabaseConsts.BookChapterTable.COLUMN_BOOK_ID, bookId)
                .orderByAsc(DatabaseConsts.BookChapterTable.COLUMN_CHAPTER_NUM);
        Page<BookChapter> bookChapterPage = bookChapterMapper.selectPage(new Page<>(page, limit), queryWrapper);
        return PageResultDto.of(
                page,
                limit,
                bookChapterPage.getTotal(),
                bookChapterPage.getRecords().stream().map(v -> BookChapterDto.builder()
                        .id(v.getId())
                        .chapterName(v.getChapterName())
                        .chapterWordCount(v.getWordCount())
                        .chapterUpdateTime(v.getUpdateTime())
                        .chapterNum(v.getChapterNum() + 1)
                        .build()).collect(Collectors.toList())
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void publishChapter(ChapterPublishVo vo, Long authorId) {
        BookInfo bookInfo = bookInfoMapper.selectById(vo.getBookId());
        if (!authorId.equals(bookInfo.getAuthorId())){
            //更新的小说不是自己的
            throw new NovelException(ResultCodeEnum.BOOK_NOT_BELONG_AUTHOR);
        }

        //TODO 之后使用多线程优化

        long lastChapterId = IdWorker.getId();
        int wordCount = StringUtil.getStrValidWordCount(vo.getChapterContent());
        LocalDateTime dateTime = LocalDateTime.now();

        //更新小说主表的信息
        BookInfo newBookInfo = new BookInfo();
        newBookInfo.setLastChapterId(lastChapterId);
        newBookInfo.setLastChapterName(vo.getChapterName());
        newBookInfo.setLastChapterUpdateTime(dateTime);
        newBookInfo.setWordCount(bookInfo.getWordCount() + wordCount);
        newBookInfo.setUpdateTime(dateTime);
        LambdaUpdateWrapper<BookInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(BookInfo::getLastChapterId, lastChapterId)
                .set(BookInfo::getLastChapterName, vo.getChapterName())
                .set(BookInfo::getLastChapterUpdateTime, dateTime)
                .set(BookInfo::getWordCount, bookInfo.getWordCount() + wordCount)
                .set(BookInfo::getUpdateTime, dateTime)
                .eq(BookInfo::getId, vo.getBookId());
        bookInfoMapper.update(newBookInfo, updateWrapper);

        int chapterNum = 0;
        if (bookInfo.getLastChapterId() != null){
            chapterNum = getLastChapterAbout(vo.getBookId()).getChapterInfo().getChapterNum() + 1;
        }

        //更新小说章节表
        BookChapter bookChapter = new BookChapter();
        bookChapter.setId(lastChapterId);
        bookChapter.setBookId(vo.getBookId());
        bookChapter.setChapterName(vo.getChapterName());
        bookChapter.setChapterNum(chapterNum);
        bookChapter.setIsVip(vo.getIsVip());
        bookChapter.setWordCount(wordCount);
        bookChapter.setCreateTime(dateTime);
        bookChapter.setUpdateTime(dateTime);
        bookChapterMapper.insert(bookChapter);

        //更新小说内容表
        BookContent bookContent = new BookContent();
        bookContent.setChapterId(lastChapterId);
        bookContent.setContent(vo.getChapterContent());
        bookContent.setCreateTime(dateTime);
        bookContent.setUpdateTime(dateTime);
        bookContentMapper.insert(bookContent);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteChapter(Long chapterId, Long authorId) {
        LambdaQueryWrapper<BookChapter> chapterQueryWrapper = new LambdaQueryWrapper<>();
        chapterQueryWrapper.eq(BookChapter::getId, chapterId);
        BookChapter bookChapter = bookChapterMapper.selectOne(chapterQueryWrapper);
        if (bookChapter == null) {
            throw new NovelException(ResultCodeEnum.CHAPTER_NOT_EXIST);
        }
        Long bookId = bookChapter.getBookId();
        LambdaQueryWrapper<BookInfo> bookInfoQueryWrapper = new LambdaQueryWrapper<>();
        bookInfoQueryWrapper.eq(BookInfo::getId, bookId);
        BookInfo bookInfo = bookInfoMapper.selectOne(bookInfoQueryWrapper);
        if (bookInfo == null){
            throw new NovelException(ResultCodeEnum.BOOK_NOT_EXIST);
        }
        if (!authorId.equals(bookInfo.getAuthorId())){
            throw new NovelException(ResultCodeEnum.BOOK_NOT_BELONG_AUTHOR);
        }
        //删除章节和内容表的内容
        bookChapterMapper.deleteById(chapterId);
        LambdaQueryWrapper<BookContent> bookContentQueryWrapper = new LambdaQueryWrapper<>();
        bookContentQueryWrapper.eq(BookContent::getChapterId, chapterId);
        bookContentMapper.delete(bookContentQueryWrapper);

        //更新总字数
        int wordCount = bookInfo.getWordCount() - bookChapter.getWordCount();
        //更新最新章节
        Long lastChapterId = null;
        String lastChapterName = null;
        LocalDateTime lastChapterUpdateTime = null;

        LambdaQueryWrapper<BookChapter> lastChapterQueryWrapper = new LambdaQueryWrapper<>();
        lastChapterQueryWrapper.eq(BookChapter::getBookId, bookId)
                .orderByAsc(BookChapter::getChapterNum);
        BookChapter lastBookChapter = bookChapterMapper.selectOne(lastChapterQueryWrapper);
        if (lastBookChapter != null){
            lastChapterId = lastBookChapter.getId();
            lastChapterName = lastBookChapter.getChapterName();
            lastChapterUpdateTime = lastBookChapter.getUpdateTime();
        }

        LambdaUpdateWrapper<BookInfo> bookInfoUpdateWrapper = new LambdaUpdateWrapper<>();
        bookInfoUpdateWrapper.set(BookInfo::getWordCount, wordCount)
                .set(BookInfo::getLastChapterId, lastChapterId)
                .set(BookInfo::getLastChapterName, lastChapterName)
                .set(BookInfo::getLastChapterUpdateTime, lastChapterUpdateTime)
                .set(BookInfo::getUpdateTime, LocalDateTime.now())
                .eq(BookInfo::getId, bookId);
        BookInfo tempBookInfo = new BookInfo();
        tempBookInfo.setId(bookId);
        tempBookInfo.setLastChapterId(lastChapterId);
        tempBookInfo.setLastChapterName(lastChapterName);
        tempBookInfo.setLastChapterUpdateTime(lastChapterUpdateTime);
        tempBookInfo.setUpdateTime(LocalDateTime.now());
        bookInfoMapper.update(tempBookInfo, bookInfoUpdateWrapper);
    }

    @Override
    public BookChapterUpdateDto getChapterInfoById(Long chapterId) {
        LambdaQueryWrapper<BookChapter> chapterQueryWrapper = new LambdaQueryWrapper<>();
        chapterQueryWrapper.eq(BookChapter::getId, chapterId);
        BookChapter bookChapter = bookChapterMapper.selectOne(chapterQueryWrapper);
        if (bookChapter == null){
            throw new NovelException(ResultCodeEnum.CHAPTER_NOT_EXIST);
        }
        LambdaQueryWrapper<BookContent> contentQueryWrapper = new LambdaQueryWrapper<>();
        contentQueryWrapper.eq(BookContent::getChapterId, chapterId);
        BookContent bookContent = bookContentMapper.selectOne(contentQueryWrapper);

        if (bookContent == null){
            throw new NovelException(ResultCodeEnum.CHAPTER_NOT_EXIST);
        }

        return BookChapterUpdateDto.builder()
                .chapterId(bookChapter.getId())
                .chapterName(bookChapter.getChapterName())
                .chapterContent(bookContent.getContent())
                .isVip(bookChapter.getIsVip())
                .build();
    }

    @Override
    public void updateBookContent(ChapterUpdateVo vo, Long authorId) {
        Long chapterId = vo.getChapterId();

        LambdaQueryWrapper<BookChapter> chapterQueryWrapper = new LambdaQueryWrapper<>();
        chapterQueryWrapper.eq(BookChapter::getId, chapterId);
        BookChapter bookChapter = bookChapterMapper.selectOne(chapterQueryWrapper);
        if (bookChapter == null) {
            throw new NovelException(ResultCodeEnum.CHAPTER_NOT_EXIST);
        }
        Long bookId = bookChapter.getBookId();
        LambdaQueryWrapper<BookInfo> bookInfoQueryWrapper = new LambdaQueryWrapper<>();
        bookInfoQueryWrapper.eq(BookInfo::getId, bookId);
        BookInfo bookInfo = bookInfoMapper.selectOne(bookInfoQueryWrapper);
        if (bookInfo == null){
            throw new NovelException(ResultCodeEnum.BOOK_NOT_EXIST);
        }
        if (!authorId.equals(bookInfo.getAuthorId())){
            throw new NovelException(ResultCodeEnum.BOOK_NOT_BELONG_AUTHOR);
        }

        LambdaUpdateWrapper<BookChapter> chapterUpdateWrapper = new LambdaUpdateWrapper<>();
        chapterUpdateWrapper
                .set(BookChapter::getChapterName, vo.getChapterName())
                .set(BookChapter::getIsVip, vo.getIsVip())
                .eq(BookChapter::getId, vo.getChapterId());
        BookChapter tempBookChapter = new BookChapter();
        tempBookChapter.setId(vo.getChapterId());
        tempBookChapter.setChapterName(vo.getChapterName());
        tempBookChapter.setIsVip(vo.getIsVip());
        bookChapterMapper.update(tempBookChapter, chapterUpdateWrapper);

        LambdaUpdateWrapper<BookContent> contentUpdateWrapper = new LambdaUpdateWrapper<>();
        contentUpdateWrapper
                .set(BookContent::getContent, vo.getChapterContent())
                .eq(BookContent::getChapterId, vo.getChapterId());
        BookContent tempBookContent = new BookContent();
        tempBookContent.setChapterId(vo.getChapterId());
        tempBookContent.setContent(vo.getChapterContent());
        bookContentMapper.update(tempBookContent, contentUpdateWrapper);
    }
}